嵌入式系统中的C++

1. 简介

嵌入式系统是指嵌入到其他设备中的计算机系统,通常用于控制、监控或执行特定任务。C++ 是一种强大的编程语言,广泛应用于嵌入式系统开发中。本教程将带你了解如何在嵌入式系统中使用C++,从基础知识到高级应用。

2. 环境搭建

2.1 编译器选择和安装

在嵌入式系统开发中,常用的编译器有 GCC 和 ARM GCC。以下是安装步骤:

  • GCC 安装:

    sudo apt-get update
    sudo apt-get install build-essential
    
  • ARM GCC 安装:

    sudo apt-get install gcc-arm-none-eabi
    

2.2 创建第一个C++程序 (Hello World)

创建一个简单的C++程序,输出 "Hello, World!":

#include <iostream>

int main() {
    std::cout << "Hello, World!" << std::endl;
    return 0;
}

编译并运行:

g++ -o hello_world hello_world.cpp
./hello_world

3. 基本语法和数据类型

3.1 基本语法

C++ 的基本语法包括变量声明、函数定义、控制流等。

3.2 数据类型

C++ 支持多种数据类型,如 int, float, double, char, bool 等。

int age = 25;
float height = 1.75;
char initial = 'J';
bool isStudent = true;

4. 变量、常量和运算符

4.1 变量

变量用于存储数据,可以随时更改。

int count = 10;
count = 20;  // 变量值可以更改

4.2 常量

常量是不可更改的值。

const int MAX_VALUE = 100;

4.3 运算符

C++ 支持多种运算符,如算术运算符、关系运算符、逻辑运算符等。

int a = 10, b = 20;
int sum = a + b;  // 算术运算符
bool isEqual = (a == b);  // 关系运算符
bool isTrue = (a < b) && (a != 0);  // 逻辑运算符

5. 函数和函数重载

5.1 函数

函数是执行特定任务的代码块。

int add(int a, int b) {
    return a + b;
}

5.2 函数重载

函数重载允许定义多个同名函数,但参数类型或数量不同。

int add(int a, int b) {
    return a + b;
}

double add(double a, double b) {
    return a + b;
}

6. 控制流

6.1 if-else

int number = 10;
if (number > 0) {
    std::cout << "Positive number" << std::endl;
} else {
    std::cout << "Non-positive number" << std::endl;
}

6.2 switch

int day = 3;
switch (day) {
    case 1:
        std::cout << "Monday";
        break;
    case 2:
        std::cout << "Tuesday";
        break;
    default:
        std::cout << "Other day";
}

6.3 for 循环

for (int i = 0; i < 5; i++) {
    std::cout << i << std::endl;
}

6.4 while 循环

int i = 0;
while (i < 5) {
    std::cout << i << std::endl;
    i++;
}

7. 数组和字符串

7.1 数组

数组是存储相同类型数据的集合。

int numbers[5] = {1, 2, 3, 4, 5};

7.2 字符串

C++ 中的字符串可以使用 std::string 类。

#include <string>

std::string name = "John";

8. 指针和引用

8.1 指针

指针存储变量的内存地址。

int value = 10;
int* ptr = &value;

8.2 引用

引用是变量的别名。

int value = 10;
int& ref = value;

9. 结构体和类

9.1 结构体

结构体是一种用户定义的数据类型。

struct Point {
    int x;
    int y;
};

9.2 类

类是面向对象编程的基础。

class Rectangle {
public:
    int width, height;
    int area() {
        return width * height;
    }
};

10. 类和对象

10.1 类

类是对象的蓝图。

class Circle {
public:
    double radius;
    double area() {
        return 3.14159 * radius * radius;
    }
};

10.2 对象

对象是类的实例。

Circle c;
c.radius = 5.0;
std::cout << "Area: " << c.area() << std::endl;

11. 封装、继承和多态

11.1 封装

封装隐藏了类的内部细节。

class Employee {
private:
    int salary;
public:
    void setSalary(int s) {
        salary = s;
    }
    int getSalary() {
        return salary;
    }
};

11.2 继承

继承允许创建新类继承现有类的特性。

class Manager : public Employee {
public:
    void setBonus(int b) {
        setSalary(getSalary() + b);
    }
};

11.3 多态

多态允许不同类的对象使用相同的接口。

class Animal {
public:
    virtual void makeSound() {
        std::cout << "Animal sound" << std::endl;
    }
};

class Dog : public Animal {
public:
    void makeSound() override {
        std::cout << "Woof!" << std::endl;
    }
};

12. 构造函数和析构函数

12.1 构造函数

构造函数在对象创建时自动调用。

class Point {
public:
    int x, y;
    Point(int x, int y) : x(x), y(y) {}
};

12.2 析构函数

析构函数在对象销毁时自动调用。

class Point {
public:
    ~Point() {
        std::cout << "Point destroyed" << std::endl;
    }
};

13. 虚函数和抽象类

13.1 虚函数

虚函数允许派生类重写基类的方法。

class Shape {
public:
    virtual void draw() {
        std::cout << "Drawing shape" << std::endl;
    }
};

class Circle : public Shape {
public:
    void draw() override {
        std::cout << "Drawing circle" << std::endl;
    }
};

13.2 抽象类

抽象类不能实例化,只能作为基类。

class Shape {
public:
    virtual void draw() = 0;  // 纯虚函数
};

14. 运算符重载

运算符重载允许自定义运算符的行为。

class Point {
public:
    int x, y;
    Point operator+(const Point& p) {
        return Point(x + p.x, y + p.y);
    }
};

15. 模板和泛型编程

15.1 模板

模板允许编写通用代码。

template <typename T>
T add(T a, T b) {
    return a + b;
}

15.2 泛型编程

泛型编程使用模板实现通用算法。

template <typename T>
void printArray(T arr[], int size) {
    for (int i = 0; i < size; i++) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
}

16. 异常处理

异常处理用于处理程序中的错误。

try {
    int x = 10, y = 0;
    if (y == 0) {
        throw "Division by zero";
    }
    int result = x / y;
} catch (const char* msg) {
    std::cerr << msg << std::endl;
}

17. 命名空间

命名空间用于避免命名冲突。

namespace MyNamespace {
    int value = 10;
}

int main() {
    std::cout << MyNamespace::value << std::endl;
    return 0;
}

18. 智能指针

智能指针自动管理内存,防止内存泄漏。

#include <memory>

std::unique_ptr<int> ptr(new int(10));
std::shared_ptr<int> sharedPtr = std::make_shared<int>(20);

19. Lambda 表达式

Lambda 表达式是匿名函数。

auto add = [](int a, int b) { return a + b; };
std::cout << add(10, 20) << std::endl;

20. 输入输出流 (iostream)

输入输出流用于处理输入输出操作。

#include <iostream>

int main() {
    int number;
    std::cout << "Enter a number: ";
    std::cin >> number;
    std::cout << "You entered: " << number << std::endl;
    return 0;
}

21. 容器 (vector, list, map)

容器用于存储和管理数据集合。

#include <vector>
#include <list>
#include <map>

std::vector<int> vec = {1, 2, 3};
std::list<int> lst = {4, 5, 6};
std::map<std::string, int> mp = {{"one", 1}, {"two", 2}};

22. 算法库

算法库提供常用算法。

#include <algorithm>
#include <vector>

std::vector<int> vec = {3, 1, 4, 1, 5};
std::sort(vec.begin(), vec.end());

23. 字符串处理 (string)

字符串处理常用函数。

#include <string>

std::string str = "Hello";
str += " World";
std::cout << str << std::endl;

24. 多线程支持 (thread)

多线程用于并发执行任务。

#include <thread>
#include <iostream>

void printMessage() {
    std::cout << "Hello from thread" << std::endl;
}

int main() {
    std::thread t(printMessage);
    t.join();
    return 0;
}

25. 动态内存分配 (new 和 delete)

动态内存分配用于在运行时分配内存。

int* ptr = new int(10);
delete ptr;

26. 内存泄漏和调试技巧

内存泄漏是指分配的内存未释放。

int* ptr = new int[100];
// 忘记释放内存

调试技巧包括使用 valgrind 等工具。

27. 智能指针详解 (unique_ptr, shared_ptr, weak_ptr)

智能指针自动管理内存。

std::unique_ptr<int> uniquePtr(new int(10));
std::shared_ptr<int> sharedPtr = std::make_shared<int>(20);
std::weak_ptr<int> weakPtr = sharedPtr;

28. 自定义内存分配器

自定义内存分配器用于优化内存管理。

template <typename T>
class MyAllocator {
public:
    T* allocate(size_t n) {
        return static_cast<T*>(::operator new(n * sizeof(T)));
    }
    void deallocate(T* p, size_t n) {
        ::operator delete(p);
    }
};

29. C++11/14/17/20 新特性概览

C++ 标准不断更新,引入新特性。

// C++11 特性
auto value = 10;
// C++14 特性
auto lambda = [](auto a, auto b) { return a + b; };
// C++17 特性
std::optional<int> opt = 10;
// C++20 特性
std::ranges::sort(vec);

30. 移动语义和右值引用

移动语义用于优化资源管理。

class MyClass {
public:
    MyClass() = default;
    MyClass(MyClass&&) = default;  // 移动构造函数
};

31. auto 和 decltype

auto 和 decltype 用于类型推导。

auto value = 10;
decltype(value) anotherValue = 20;

32. 范围for循环

范围for循环简化遍历容器。

std::vector<int> vec = {1, 2, 3};
for (int value : vec) {
    std::cout << value << std::endl;
}

33. 初始化列表

初始化列表用于初始化对象。

class Point {
public:
    int x, y;
    Point(int x, int y) : x(x), y(y) {}
};

34. 常用设计模式在C++中的实现

设计模式是解决常见问题的最佳实践。

// 单例模式
class Singleton {
public:
    static Singleton& getInstance() {
        static Singleton instance;
        return instance;
    }
private:
    Singleton() = default;
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
};

35. SOLID原则

SOLID原则是面向对象设计的指导原则。

  • 单一职责原则:一个类只负责一个功能。
  • 开放封闭原则:类应开放扩展,封闭修改。
  • 里氏替换原则:派生类应能替换基类。
  • 接口隔离原则:接口应小而专。
  • 依赖倒置原则:依赖抽象,不依赖具体。

36. 代码重构技巧

代码重构用于改进代码质量。

// 重构前
void processData(int data) {
    if (data > 0) {
        // 处理正数
    } else {
        // 处理负数
    }
}

// 重构后
void processPositiveData(int data) {
    // 处理正数
}

void processNegativeData(int data) {
    // 处理负数
}

void processData(int data) {
    if (data > 0) {